/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.ha.jmx;

import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.ha.deploy.FarmWarDeployer;
import org.apache.catalina.ha.tcp.SimpleTcpCluster;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.modeler.ManagedBean;
import org.apache.tomcat.util.modeler.Registry;

import javax.management.DynamicMBean;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;

/**
 * @author Filip Hanik
 * @deprecated Unused - registration now happens via
 * {@link org.apache.catalina.util.LifecycleMBeanBase}
 */
@Deprecated
public class ClusterJmxHelper {

	private static final Log log = LogFactory.getLog(ClusterJmxHelper.class);
	protected static Registry registry = Registry.getRegistry(null, null);
	protected static boolean jmxEnabled = true;

	protected static MBeanServer mbeanServer = null;

	public static Registry getRegistry() {
		return registry;
	}

	public static MBeanServer getMBeanServer() throws Exception {
		if (mbeanServer == null) {
			if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
				mbeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
			} else {
				mbeanServer = MBeanServerFactory.createMBeanServer();
			}
		}
		return mbeanServer;
	}

	protected static boolean initMetaData(Class<?> clazz) {
		try {
			if (clazz == null) return false;
			getRegistry().loadMetadata(clazz.getResourceAsStream("mbeans-descriptors.xml"));
		} catch (Exception x) {
			log.warn("Unable to load meta data for class:" + clazz.getName());
			return false;
		}
		return true;
	}

	public static DynamicMBean getManagedBean(Object object) throws Exception {
		DynamicMBean mbean = null;
		if (getRegistry() != null) {
			ManagedBean managedBean = registry.findManagedBean(object.getClass().getName());
			mbean = managedBean.createMBean(object);
		}
		return mbean;
	}

	protected static void initDefaultCluster() {
		initMetaData(SimpleTcpCluster.class);
		initMetaData(FarmWarDeployer.class); //not functional yet
	}

	public static boolean registerDefaultCluster(SimpleTcpCluster cluster) {
		try {
			initDefaultCluster();
			ObjectName clusterName = getDefaultClusterName(cluster);
			if (!getMBeanServer().isRegistered(clusterName)) {
				getMBeanServer().registerMBean(getManagedBean(cluster), clusterName);
			}
			return true;
		} catch (Exception x) {
			log.warn("Unable to register default cluster implementation with JMX", x);
			return false;
		}
	}

	public static boolean unregisterDefaultCluster(SimpleTcpCluster cluster) {
		try {
			ObjectName clusterName = getDefaultClusterName(cluster);
			if (getMBeanServer().isRegistered(clusterName)) {
				getMBeanServer().unregisterMBean(clusterName);
			}
			return true;
		} catch (Exception x) {
			log.warn("Unable to unregister default cluster implementation with JMX", x);
			return false;
		}
	}

	private static ObjectName getDefaultClusterName(SimpleTcpCluster cluster) throws Exception {
		String domain = getMBeanServer().getDefaultDomain();
		String type = ":type=";
		String clusterType = type + "Cluster";
		if (cluster.getContainer() instanceof StandardHost) {
			domain = ((StandardHost) cluster.getContainer()).getDomain();
			clusterType += ",host=" + cluster.getContainer().getName();
		} else {
			if (cluster.getContainer() instanceof StandardEngine) {
				domain = ((StandardEngine) cluster.getContainer()).getDomain();
			}
		}
		ObjectName clusterName = new ObjectName(domain + clusterType);
		return clusterName;
	}

}